package utils

import (
	"MySQL_BackUp/models"
	"bytes"
	"fmt"
	"os"
	"text/template"

	"gopkg.in/yaml.v2"
)

/*
	用于解决yaml文件包含{{ .xxx }}这种模板变量的

	主要思想就是读取 YAML 文件并将其内容解析为包含 结构体,然后结合"text/template" 标准库对其模板变量进行解析赋值
*/
// 用于解析和填充配置模板字符串
func ParseConfigTemplate(configStr string, data map[string]string) (string, error) {
	/*
		template.New("config") 创建一个新的模板对象，其名称为 "config"
		Parse(configStr) 方法解析传入的模板字符串 configStr。
	*/
	tmpl, err := template.New("config").Parse(configStr)
	if err != nil {
		return "", err
	}
	/*
		var buf bytes.Buffer 创建一个缓冲区，用于存储模板执行后的输出结果。
		tmpl.Execute(&buf, data) 方法将模板与数据结合并将结果写入 buf 中。
			&buf 是指向缓冲区的指针。
			data 是包含要填充模板的数据的映射。
		将缓冲区中的内容转换为字符串，并且返回结果和 nil 表示没有错误
	*/
	var buf bytes.Buffer
	if err := tmpl.Execute(&buf, data); err != nil {
		return "", err
	}

	return buf.String(), nil
}

// 读取yaml文件并进行模板加载
func LoadConfig(yamlFilePath string, data map[string]string) (*models.Config, error) {
	// 读取yaml文件
	configFile, err := os.ReadFile(yamlFilePath)
	if err != nil {
		return nil, fmt.Errorf("failed to read config file: %w", err)
	}

	/*
		yaml.Unmarshal(configFile, &config) 将 YAML 文件的内容解析为 models.Config 结构体。
		如果解析过程中出现错误，则返回相应的错误信息。
	*/
	var config models.Config
	err = yaml.Unmarshal(configFile, &config)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal config: %w", err)
	}

	// yaml文件中包含 模板变量的结构体字段
	fields := []*string{
		&config.ExpiredDay,
		&config.CurrentDay,
		&config.BackupPath,
		&config.LogPath,
		&config.BinlogPath,
		&config.LogFile,
		&config.BinlogFile,
		&config.BinlogPathFileSrc,
		&config.MyCnf,
		&config.MySock,
	}
	/*
		对于结构体中的每个字段，都使用 ParseConfigTemplate 函数处理其中可能包含的模板变量。
		对字段的值进行了处理，并将处理后的值赋回到原始的结构体字段中。
		如果处理过程中出现错误，则返回相应的错误信息。
	*/
	for _, field := range fields {
		processedValue, err := ParseConfigTemplate(*field, data)
		if err != nil {
			return nil, fmt.Errorf("failed to process template: %w", err)
		}
		*field = processedValue
	}
	return &config, nil
}
